package com.atguigu.gulimall.search.thread;

import java.util.concurrent.*;

public class ThreadTest {

    public static ExecutorService executorService = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        /*********
         * CompletableFuture.runAsync()无返回值，不阻塞
         * CompletableFuture.supplyAsync()有返回值，阻塞
         * *******/
//        System.out.println("main......start");
//        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果" + i);
//        }, executorService);
//        System.out.println("main......end");

        /****
         * 方法执行后的处理
         * 可修改返回值
         * handle与handleAsync区别
         *      handle只使用当前线程处理，handleAsync开启新线程处理
         */
//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("main......start");
//            System.out.println("当前线程：" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果" + i);
//            return i;
//        }, executorService).handle((response,exception) ->{  //response返回值,exception异常
//            try {
//                Thread.sleep(3000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println("response值为"+response);
//            if (response != null){
//                return response*2;
//            }
//            if (exception != null){
//                return 0;
//            }
//            return 0;
//        });
////        Integer i = future.get();
        CompletableFuture<Object> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println(System.currentTimeMillis());
            System.out.println("future1开始执行");
            return "future1执行";
        }, executorService);
        CompletableFuture<Object> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println(System.currentTimeMillis());
                System.out.println("future2开始执行");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "future2执行";
        }, executorService);
        CompletableFuture<Object> future3 = CompletableFuture.supplyAsync(() -> {
            System.out.println(System.currentTimeMillis());
            System.out.println("future3开始执行");
            return "future3执行";
        }, executorService);
        CompletableFuture allOf = CompletableFuture.allOf(future1, future2, future3);

        System.out.println("main......end"+future1.get()+"-----"+future2.get()+"-----"+future3.get());
        System.out.println("主线程时间"+System.currentTimeMillis());
//        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future1, future2, future3);
//        System.out.println("main......end"+anyOf.get());
    }

    public static void main1(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main......start");
        /***
         * //TODO  线程的创建
         * 无论如何，启动线程都是  new Thread(...).start()
         *
         * 1.继承Thread
         *      new Thread01().start();//启动线程
         *      System.out.println("main......end");
         * 2.实现Runnable接口
         *      new Thread(new Runnable01()).start();//启动线程
         * 3.实现Callable接口 + FutureTask （可以拿到返回结果，可以处理异常）
         *     FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
         *         new Thread(futureTask).start();
         *         //阻塞   等待整个线程执行完成，获取返回结果才进行下一步操作
         *         Integer integer = futureTask.get();
         * 4.线程池
         *      给线程池直接提交任务
         *      ExecutorService executorService = Executors.newFixedThreadPool(10);
         *         Future<Integer> future = executorService.submit(new Callable01());
         *         Integer i = future.get();
         *
         * 一般系统只有一两个线程池（核心与非核心业务），每个异步任务，提交线程池让他自己去执行即可
         *
         * 区别：
         *      12不能获取返回值，3可以获取返回值
         *      1/2/3都不能控制资源，造成资源浪费
         *
         */

        /**
         * TODO 线程池七大参数
         *
         ** 1、corePoolSize:[5]核心线程数[-直存在除非设置(allowCoreThreadTimeOut) ];线程池，创建好以后就准备
         *                  5个Thread thread = new Thread();. thread. start();
         *  2、maximumPoolSize:[200] 最大线程数量; 控制资源
         *  3、keepAliveTime :存活时间。如果当前的线程数量大于core数量。
         *      释放空闲的线程(maximumPoolSize-corePoolSize),注意不能释放掉核心core 。只要线程空闲大于指定的keepAliveTime;
         *  4、unit:时间单位
         *  5、BlockingQueue<Runnable> workQueue: 阻塞队列。如果任务有很多，就会将目前多的任务放在队列里面。
         *                                          只要有线程空闲，就会去队列里面取出新的任务继续执行。
         *  6、threadFactory:线程的创建工厂。
         *  7、RejectedExecutionHandler handler:如果队列满了，按照我们指定的拒绝策略拒绝执行任务
         *
         * *工作顺序:
         * * 1)、线程池创建，准备好core数量的核心线程，准备接受任务
         * * 1.1、core满了，就将再进来的任务线程放入阻塞队列中。只要核心线程core有空闲，就会去阻塞队列获取任务执行
         * * 1.2、阻塞队列满了,就直接开新线程执行，最大只能开到max指定的数量
         *   1.3、max满了就用RejectedExecutionHandler拒绝任务
         * * 1.4、 max都执行完成，有很多空闲.在指定的时间keepAliveTime以后，释放max-core这些线程
         * *
         * *
         * new LinkedBlockingDeque<>(): 默认是Integer的最大值。一般需要指定数值，否则会占满内存，导致其它任务不能正常进行，出现内存不够
         * *
         * *一个线程池core 7; max 20，queue: 5e， 100并发进来怎么分配的;
         * * 7个会立即得到执行，5e个会进入队列，再开13个进行执行。剩下的30个就使用拒绝策略
         */
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,
                200,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),//一般是压力测试后得到的值
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
                );
        System.out.println("main......end");
    }

    public static class Callable01 implements Callable<Integer>{ //Integer返回值类型
        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程："+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果"+i);
            return i;
        }
    }
    public static class Thread01 extends Thread{
        @Override
        public void run() {
            System.out.println("当前线程："+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果"+i);
        }
    }
    public static class Runnable01 implements Runnable{

        @Override
        public void run() {
            System.out.println("当前线程："+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果"+i);
        }
    }


}
